
#region using Statements

using System;
using System.Data;
using System.DirectoryServices;
using System.Configuration;
using System.Collections.Specialized;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

#endregion

namespace Windows.Live.SSO
{
    public static class ADSI
    {

        #region LookupWLID
        /// <summary>
        /// Method "queries" ADSI aware directory for Windows Live ID attribute value
        /// </summary>
        /// <param name="LDAPattributeValue">Value of the "anchor" attribute in LDAP directory</param>
        /// <param name="WLIDattributeName">Name of the attribute containing Windows Live ID</param>
        /// <returns>Value of the attribute containing Windows Live ID of specified user</returns>
        public static string LookupWLID(string LDAPattributeValue, string WLIDattributeName)
        {
            // Get the current Forest Root DN
            string forestDn = String.Empty;
            HttpContext webContext = HttpContext.Current;
            if ((webContext.Application["ForestDN"] == null) || (String.IsNullOrEmpty(webContext.Application["ForestDN"].ToString())))
            {
                try
                {
                    webContext.Application.Lock();

                    using (DirectoryEntry rootDSE = GetDirectoryEntry("LDAP://rootDSE"))
                    {
                        forestDn = rootDSE.Properties["rootDomainNamingContext"].Value.ToString();
                    }
                    webContext.Application["ForestDN"] = forestDn;
                }
                finally
                {
                    try
                    {
                        webContext.Application.UnLock();
                    }
                    catch { }
                }
            }
            else
            {
                forestDn = webContext.Application["ForestDN"].ToString();
            }

            string filterAttributeName = "sAMAccountName";
            if (LDAPattributeValue.Contains("@"))
            {
                filterAttributeName = "userPrincipalName";
            }

            // Search the global catalog
            using (DirectoryEntry de = GetDirectoryEntry("GC://" + forestDn))
            {
                using (DirectorySearcher ds = new DirectorySearcher(de))
                {
                    StringBuilder filter = new StringBuilder();
                    filter.Append("(&(objectCategory=Person)(objectClass=user)");
                    filter.Append("(" + filterAttributeName + "=" + LDAPattributeValue + "))");

                    ds.PropertiesToLoad.Add(WLIDattributeName);
                    ds.Filter = filter.ToString();
                    ds.SearchScope = SearchScope.Subtree;
                    using (SearchResultCollection results = ds.FindAll())
                    {
                        try
                        {
                            int resultCount = results.Count;
                            if (resultCount > 0)
                            {
                                return results[0].Properties[WLIDattributeName][0].ToString();
                            }
                        }
                        catch { }
                    }
                }
            }

            return String.Empty;
        }
        #endregion

        #region GetDirectoryEntry

        private static DirectoryEntry GetDirectoryEntry(string path)
        {
            DirectoryEntry de = new DirectoryEntry();
            de.Path = path;
            de.AuthenticationType = AuthenticationTypes.Delegation;
            de.AuthenticationType = de.AuthenticationType | AuthenticationTypes.Signing;
            de.AuthenticationType = de.AuthenticationType | AuthenticationTypes.Sealing;
            de.AuthenticationType = de.AuthenticationType | AuthenticationTypes.FastBind;
            return de;
        }
        #endregion

    }
}